package com.springsource.boot.run;

import org.springframework.boot.DefaultBootstrapContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.support.SpringFactoriesLoader;

import java.lang.reflect.Constructor;
import java.util.List;

@Configuration
public class SpringbootRunListeners {


    public static void main(String[] args) throws Exception{
        SpringApplication app = new SpringApplication();
        // 添加监听器
        app.addListeners(event -> System.out.println(event.getClass()));

        // 事件发布器 SpringApplicationRunListener
        List<String> names = SpringFactoriesLoader.loadFactoryNames(SpringApplicationRunListener.class, SpringbootRunListeners.class.getClassLoader());
        for (String name : names) {
            Class<?> clazz = Class.forName(name);
            Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(SpringApplication.class, String[].class);
            SpringApplicationRunListener publisher = ((SpringApplicationRunListener) declaredConstructor.newInstance(app, args));

            // 先run了才能有这几个变量，但是先run了事件就发布完了
            DefaultBootstrapContext defaultBootstrapContext = new DefaultBootstrapContext();
            StandardEnvironment environment = new StandardEnvironment();
            GenericApplicationContext context = new GenericApplicationContext();

            // springboot开始启动
            publisher.starting(defaultBootstrapContext);

            // springboot环境准备完成
            publisher.environmentPrepared(defaultBootstrapContext, environment);

            // spring容器创建并调用初始化器之后
            publisher.contextPrepared(context);

            // spring容器将全部BeanDefinition加载完成
            publisher.contextLoaded(context);

            context.refresh();
            // Spring容器初始化完成，也就是refresh 方法执行完成
            publisher.started(context);

            // springboot启动完成
            publisher.running(context);

            // springboot启动失败
            publisher.failed(context, new Exception("failed"));
        }

    }


}
